﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;

namespace CreatePD
{
    public partial class MainFrm : Form
    {
        public MainFrm()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 文件夹地址
        /// </summary>
        private string folderPath = "";


        /// <summary>
        /// PD文件地址
        /// </summary>
        private string pdFilePath = "";

        /// <summary>
        /// 接口
        /// </summary>
        private string JieKou = "";

        /// <summary>
        /// 已修改过忽略
        /// </summary>
        private bool isIgnore = false;


        /// <summary>
        /// 修改描述
        /// </summary>
        private bool isRemake = false;

        /// <summary>
        /// 选择PD文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPDSelect_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog2 = new OpenFileDialog();
            openFileDialog2.Filter = "PD文件(*.pdm)|*.pdm";
            if (openFileDialog2.ShowDialog() == DialogResult.OK)
            {
                PDPath.Text = openFileDialog2.FileName;

            }
        }

        /// <summary>
        /// 选择文件夹
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnFolderSelect_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
            if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
            {
                dllPath.Text = folderBrowserDialog.SelectedPath;
            }
        }

        /// <summary>
        /// 开始
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStart_Click(object sender, EventArgs e)
        {
            pdFilePath = PDPath.Text;
            folderPath = dllPath.Text;
            JieKou = InterfaceName.Text.Trim();
            isIgnore = ckIgnore.Checked;
            isRemake = ckRemake.Checked;
            if (string.IsNullOrWhiteSpace(pdFilePath) || string.IsNullOrWhiteSpace(folderPath) || string.IsNullOrWhiteSpace(JieKou))
            {
                MessageBox.Show("文件地址或接口不可为空");
                return;
            }
            btnStart.Enabled = false;
            WriteMsg("开始");
            Thread thread = new Thread(HandlePD);
            thread.IsBackground = true;
            thread.Start();
        }

        private void HandlePD()
        {
            PdmFileReader pdmFileReader = new PdmFileReader();
            var model = pdmFileReader.ReadFromFile(pdFilePath);
            SetModel(model);
            WriteMsg("保存作业");
            pdmFileReader.Save(WriteMsg);

            WriteMsg("完成");
            btnStart.Invoke(new Action(() =>
            {
                btnStart.Enabled = true;
            }));
        }


        /// <summary>
        /// 设置消息
        /// </summary>
        /// <param name="msg"></param>
        private void WriteMsg(string msg)
        {
            if (LabMsg.InvokeRequired)
            {
                LabMsg.Invoke(new Action<string>(p =>
                    LabMsg.Text = p
                ), msg);
            }
            else
                LabMsg.Text = msg;
        }



        /// <summary>
        /// 设置Model
        /// </summary>
        private void SetModel(PdmModels models)
        {
            WriteMsg("加载DLL...");
            var dir = new DirectoryInfo(folderPath);//($@"F:\医院物流管理系统\05 医院物流管理系统(改进版)\02 代码类\01 源代码\08 SPD耗材物流管理系统\QuickShare.MaterialSpd.API\QuickShare.MaterialSpd.Web\bin");
            var files = dir.GetFiles("*.dll");//.Where(p => p.Name.Contains("Winning.DMSP.Domain"))
            List<Assembly> assemblies = new List<Assembly>();
            foreach (var file in files)
            {
                var ass = Assembly.Load(AssemblyName.GetAssemblyName(file.FullName));
                assemblies.Add(ass);
            }

            List<Type> types = new List<Type>();
            foreach (var item in assemblies)
            {
                try
                {
                    types.AddRange(item.ExportedTypes.Where(p => p.IsClass && p.GetInterface(JieKou) != null).ToList());
                }
                catch
                {
                    continue;
                }
            }
            types = types.OrderBy(p => p.Assembly.FullName).ToList();
            WriteMsg("开始分析表...");
            foreach (var item in types.GroupBy(p => p.Assembly.FullName).ToList())
            {
                var path = Path.Combine(folderPath, item.First().Module.Name.Replace(".dll", ".xml"));
                if (!File.Exists(path))
                    continue;
                XDocument doc = GetXDocument(path);
                foreach (var type in item.ToList())
                {
                    string pubName = "PUB_" + type.Name;

                    string busName = "BUS_" + type.Name;
                    var table = models.Tables.Where(p => p.Code == type.Name || p.Code == pubName || p.Code == busName).FirstOrDefault();
                    if (table != null)
                    {
                        WriteMsg($"分析表{table.Code}");
                        foreach (var colunmn in table.Columns)
                        {
                            if ((isIgnore && colunmn.Name != colunmn.Code) || (!isIgnore))
                            {
                                var math = $"P:{type.Namespace}.{type.Name}.{colunmn.Code}";
                                var value = doc.Descendants().Where(p => p.Name == "member" && p.Attribute("name").Value == math).FirstOrDefault()?.Element("summary")?.Value;
                                if (value == null)
                                {
                                    value = GetValue(type, colunmn.Code);
                                }
                                value = value?.Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace(" ", "");
                                colunmn.Name = value ?? colunmn.Name;
                                if (isRemake)
                                {
                                    value = doc.Descendants().Where(p => p.Name == "member" && p.Attribute("name").Value == math).FirstOrDefault()?.Element("remarks")?.Value;
                                    if (value == null)
                                    {
                                        value = GetValue(type, colunmn.Code, "remarks");
                                    }
                                    value = value?.Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace(" ", "");
                                    colunmn.Description = value;
                                }
                            }
                        }

                    }
                }


            }
        }

        Dictionary<string, XDocument> dic = new Dictionary<string, XDocument>();

        private string GetValue(Type type, string Code, string elment = "summary")
        {
            var proprty = type.GetProperty(Code);
            if (proprty == null)
                return null;
            var path = Path.Combine(folderPath, proprty.Module.Name.Replace(".dll", ".xml"));
            if (!File.Exists(path))
                return null;
            XDocument doc = GetXDocument(path);
            var math = $"P:{proprty.DeclaringType.Namespace}.{proprty.DeclaringType.Name}.{Code}";
            var value = doc.Descendants().Where(p => p.Name == "member" && p.Attribute("name").Value == math).FirstOrDefault()?.Element(elment)?.Value;
            return value;
        }


        private XDocument GetXDocument(string path)
        {
            if (dic.Keys.Contains(path))
                return dic[path];
            XDocument doc = XDocument.Load(path);
            dic.Add(path, doc);
            return doc;
        }

    }
}
